package com.ryan.mdp.json;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.module.SimpleModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.remoting.support.RemoteInvocation;
import org.springframework.util.ClassUtils;

import com.ryan.mdp.callback.MdpCallback;
import com.ryan.mdp.exception.MdpError;
import com.ryan.mdp.exception.MdpException;

public class JsonMessageConverter implements MessageConverter {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private final static ObjectMapper mapper = new ObjectMapper();;

    @SuppressWarnings("deprecation")
    public JsonMessageConverter() {
        mapper.getSerializationConfig().disable(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS);
        SimpleModule desModule = new SimpleModule("MdpModule", new Version(1, 0, 0, null));
        desModule.addDeserializer(RemoteInvocation.class, new RemoteInvocationDeserializer(RemoteInvocation.class));
        desModule.addDeserializer(MdpInvocationResult.class, new MdpInvocationResultDeserializer(
                MdpInvocationResult.class));
        desModule.addDeserializer(MdpCallback.class, new MdpCallbackDeserializer(MdpCallback.class));
        mapper.registerModule(desModule);
    }

    public Object fromMessage(Message msg) throws JMSException, MessageConversionException {
        if (!(msg instanceof TextMessage)) {
            throw new MdpError("01020013", msg);
        }
        String json = ((TextMessage) msg).getText();
        logger.debug("received message content:" + json);
        int clazzIndex = json.indexOf(":");
        String clazzName = json.substring(0, clazzIndex);
        json = json.substring(clazzIndex + 1);
        try {
            Class<?> clazz = ClassUtils.forName(clazzName);
            Object object = mapper.readValue(json, clazz);
            return object;
        } catch (Exception e) {
            throw new MdpException("01020020", e, json);
        }
    }

    public Message toMessage(Object arg, Session session) throws JMSException, MessageConversionException {
        if (arg != null) {
            String clazz = arg.getClass().getName();
            try {
                String json = clazz + ":" + mapper.writeValueAsString(arg);
                logger.debug("sending message content:" + json);
                return session.createTextMessage(json);
            } catch (Exception e) {
                throw new MdpException("01020025", e, arg);
            }
        } else {
            return session.createTextMessage();
        }
    }

    public static ObjectMapper getMapper() {
        return mapper;
    }
}
